<template>
  <Drawer
    :visible="props.visible"
    :title="props.title"
    :width="drawerWidth"
    :modal="drawerModal"
    @close="closeDrawer"
  >
    <template #drawer-content>
      <el-form
        :model="spuForm"
        :rules="rules"
        label-width="auto"
        ref="spu"
        style="max-width: 600px; margin: auto"
      >
        <el-form-item label="SPU名称" prop="spuName">
          <el-input v-model="spuForm.spuName" placeholder="请输入SPU名称" />
        </el-form-item>
        <el-form-item label="SPU品牌" prop="tmId">
          <el-select v-model="spuForm.tmId" placeholder="请选择SPU品牌">
            <el-option
              v-for="item in allTrademark"
              :key="item.id"
              :label="item.tmName"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="SPU描述">
          <el-input
            v-model="spuForm.description"
            type="textarea"
            :rows="2"
            placeholder="请输入SPU的描述"
          />
        </el-form-item>
        <el-form-item label="SPU图片">
          <el-upload
            v-model:file-list="fileList"
            action="/api/admin/product/fileUpload"
            list-type="picture-card"
            :on-preview="handlePictureCardPreview"
            :before-upload="handleBeforeUpload"
          >
            <el-icon><Plus /></el-icon>
          </el-upload>
        </el-form-item>
        <el-form-item label="SPU销售属性">
          <el-select
            v-model="saleAttrIdAndValueName"
            :placeholder="
              unSelectSaleAttr.length
                ? `还未选择${unSelectSaleAttr.length}个`
                : '暂无数据可选择'
            "
            style="
              width: calc(100% - 125px);
              margin-right: 15px;
              margin-bottom: 15px;
            "
          >
            <el-option
              v-for="item in unSelectSaleAttr"
              :key="item.id"
              :label="item.name"
              :value="`${item.id}:${item.name}`"
            />
          </el-select>
          <el-button
            type="primary"
            icon="Plus"
            :disabled="saleAttrIdAndValueName ? false : true"
            @click="addSaleAttr"
            style="margin-bottom: 15px"
          >
            添加属性
          </el-button>
          <el-table :data="saleAttr" :border="true" max-height="400px">
            <el-table-column
              type="index"
              label="序号"
              width="80"
              align="center"
            />
            <el-table-column prop="saleAttrName" label="属性" width="80" />
            <el-table-column prop="spuName" label="属性值">
              <template #default="{ row, $index }">
                <el-space wrap>
                  <el-tag
                    v-for="(o, idx) in row.spuSaleAttrValueList"
                    :key="o.id"
                    type="primary"
                    closable
                    @close="row.spuSaleAttrValueList.splice(idx, 1)"
                  >
                    {{ o.saleAttrValueName }}
                  </el-tag>
                  <el-input
                    v-if="row.flag"
                    v-model="row.saleAttrValue"
                    placeholder="请输入属性值"
                    style="width: 120px"
                    :ref="(vc: any) => (inputRefs[$index] = vc)"
                    @blur="changeMode(row)"
                  />
                  <el-button
                    v-else
                    type="primary"
                    icon="plus"
                    size="small"
                    @click="toEdit(row, $index)"
                  />
                </el-space>
              </template>
            </el-table-column>
            <el-table-column prop="action" label="操作" width="80">
              <template #default="{ $index }">
                <el-tooltip
                  class="box-item"
                  effect="dark"
                  content="删除"
                  placement="bottom"
                >
                  <el-button
                    type="danger"
                    icon="delete"
                    @click="deleteSaleAttrItem($index)"
                  ></el-button>
                </el-tooltip>
              </template>
            </el-table-column>
          </el-table>
        </el-form-item>
      </el-form>
      <el-dialog v-model="dialogVisible">
        <img w-full :src="dialogImageUrl" alt="Preview Image" />
      </el-dialog>
    </template>
    <template #drawer-footer>
      <el-space wrap>
        <el-button
          type="primary"
          :disabled="saleAttr.length > 0 ? false : true"
          @click="saveSpu"
        >
          保存
        </el-button>
        <el-button @click="cancel">取消</el-button>
      </el-space>
    </template>
  </Drawer>
</template>

<script setup lang="ts" name="Spu">
import { ref, withDefaults, watch, computed, nextTick, onMounted } from 'vue'
import {
  reqAllTrademarkList,
  reqSpuImage,
  reqSpuSaleAttr,
  reqAllSpuSaleAttr,
  addOrUpdateSpuReq
} from '@/api/product/spu'
import { ElMessage, type UploadProps } from 'element-plus'

interface Props {
  visible: boolean
  title: string
  spuId?: string | number
  category3Id?: string | number
  data: object
}

interface Emits {
  (event: 'success', isShow: boolean): void
  (event: 'closeDrawer', isShow: boolean): void
}

const props = withDefaults(defineProps<Props>(), {
  visible: false,
  title: '添加SPU',
  spuId: '',
  category3Id: '',
  data: () => {
    {
      return {}
    }
  }
})

onMounted(() => {
  initData()
})

watch(
  () => props.visible,
  val => {
    if (val) {
      initData()
    }
  }
)

const initData = () => {
  getAllTrademarkList()
  getAllSpuSaleAttr()
  if (props.spuId) {
    getSpuImage(props.spuId)
    getSpuSaleAttr(props.spuId)
    spuForm.value = JSON.parse(JSON.stringify(props.data))
  } else {
    Object.assign(spuForm.value, {
      category3Id: '',
      spuName: '',
      tmId: '',
      description: '',
      spuImageList: [],
      spuSaleAttrList: []
    })
    fileList.value = []
    saleAttr.value = []
    saleAttrIdAndValueName.value = ''
    spuForm.value.category3Id = props.category3Id
    delete spuForm.value.id
  }
}

// 计算还未选择的销售属性
const unSelectSaleAttr = computed(() => {
  let attrAry = allSaleAttr.value.filter((item: any) => {
    return saleAttr.value.every((o: any) => item.name !== o.saleAttrName)
  })
  return attrAry
})

let drawerWidth = ref(800)
let drawerModal = ref(true)
let allTrademark = ref<any>([]) // 所有商品
let saleAttr = ref<any>([]) // 已有商品属性
let allSaleAttr = ref<any>([]) // 所有商品属性
let saleAttrIdAndValueName = ref('')
let spuForm = ref<any>({
  category3Id: '',
  spuName: '',
  tmId: '',
  description: '',
  spuImageList: [],
  spuSaleAttrList: []
})
let rules = {
  spuName: { required: true, message: 'SPU名称不能为空', trigger: 'blue' },
  tmId: { required: true, message: 'SPU品牌不能为空', trigger: 'blue' }
}
let fileList = ref([])
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const emits = defineEmits<Emits>()
const inputRefs = ref<HTMLElement[]>([]) // 存储遍历的input的ref
const spu = ref()

// 查询商品
const getAllTrademarkList = async () => {
  let res: any = await reqAllTrademarkList()
  if (res.code === 200) {
    allTrademark.value = res.data
  } else {
    ElMessage.error(res.message)
  }
}

//查询商品图片
const getSpuImage = async (spuId: any) => {
  let res: any = await reqSpuImage(spuId)
  if (res.code === 200) {
    fileList.value = res.data.map((item: any) => {
      return { ...item, name: item.imgName, url: item.imgUrl }
    })
  } else {
    ElMessage.error(res.message)
  }
}

// 查询已有的销售属性
const getSpuSaleAttr = async (spuId: any) => {
  let res: any = await reqSpuSaleAttr(spuId)
  if (res.code === 200) {
    saleAttr.value = res.data
  } else {
    ElMessage.error(res.message)
  }
}

// 查询所有的销售属性
const getAllSpuSaleAttr = async () => {
  let res: any = await reqAllSpuSaleAttr()
  if (res.code === 200) {
    allSaleAttr.value = res.data
  } else {
    ElMessage.error(res.message)
  }
}

const handleBeforeUpload = (file: any) => {
  if (
    file.type === 'image/png' ||
    file.type === 'image/jpeg' ||
    file.type === 'image/gif'
  ) {
    if (file.size / 1024 / 1024 <= 5) {
      return true
    } else {
      ElMessage.error('文件不能大于5MB！')
      return false
    }
  } else {
    ElMessage.error('上传文件格式不正确！')
    return false
  }
}

const handlePictureCardPreview: UploadProps['onPreview'] = uploadFile => {
  dialogImageUrl.value = uploadFile.url!
  dialogVisible.value = true
}

// 添加属性
const addSaleAttr = () => {
  const [baseSaleAttrId, saleAttrName] = saleAttrIdAndValueName.value.split(':')
  let newSaleAttr: any = {
    baseSaleAttrId,
    saleAttrName,
    spuSaleAttrValueList: []
  }
  saleAttr.value.push(newSaleAttr)
  saleAttrIdAndValueName.value = ''
}

// 控制编辑与只读模式的方法
const changeMode = (data: any) => {
  const { baseSaleAttrId, saleAttrValue } = data
  // 非空判断
  if (saleAttrValue.trim() == '') {
    return ElMessage.error('属性值不能为空')
  }
  // 重复判断
  let isRepeat = data.spuSaleAttrValueList.some((item: any) => {
    return item.saleAttrValueName === saleAttrValue
  })
  if (isRepeat) {
    return ElMessage.error('属性值不能重复')
  }
  let newSaleAttrValue: any = {
    baseSaleAttrId,
    saleAttrValueName: saleAttrValue
  }
  data.spuSaleAttrValueList.push(newSaleAttrValue)
  data.flag = false
}

const toEdit = (data: any, idx: number) => {
  data.flag = true
  data.saleAttrValue = ''
  nextTick(() => {
    inputRefs.value[idx].focus()
  })
}

// 删除属性
const deleteSaleAttrItem = (idx: number) => {
  saleAttr.value.splice(idx, 1)
}

// 保存/编辑方法
const addOrUpdateSpu = async (data: any) => {
  let isAdd = data.id ? false : true
  let res: any = await addOrUpdateSpuReq(data)
  if (res.code === 200) {
    ElMessage.success(res.message)
    emits('success', isAdd)
  } else {
    ElMessage.error(res.message)
  }
}

// 保存
const saveSpu = async () => {
  await spu.value.validate(async (valid: any) => {
    if (valid) {
      spuForm.value.spuImageList = fileList.value.map((item: any) => {
        return {
          imgName: item.name,
          imgUrl: item.url
        }
      })
      spuForm.value.spuSaleAttrList = saleAttr.value
      addOrUpdateSpu(spuForm.value)
    }
  })
}

// 取消
const cancel = () => {
  emits('closeDrawer', false)
}

// drawer 关闭回调
const closeDrawer = (value: boolean) => {
  emits('closeDrawer', value)
}
</script>

<style scoped></style>
